package com.csw.compose.ui.module.component.container

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.csw.compose.theme.pagePadding
import com.csw.compose.ui.Destination
import com.csw.compose.ui.components.BodyText
import com.csw.compose.ui.components.LabelText
import com.csw.compose.ui.components.LargeSpacer
import com.csw.compose.ui.components.MiniSpacer
import com.csw.compose.ui.components.OlItem
import com.csw.compose.ui.components.PrimaryTitle
import com.csw.compose.ui.components.UlItem
import com.csw.compose.ui.module.BasePage
import kotlinx.coroutines.launch

@Preview(heightDp = 1800)
@Composable
fun LazyListPreview() {
    BasePage({}, "列表组件（LazyList）") { LazyListPage() }
}

class LazyListData {
    companion object : Destination("LazyListPage")
}

/**
 * [列表与网格](https://developer.android.google.cn/develop/ui/compose/lists?hl=zh-cn)
 */
@OptIn(ExperimentalLayoutApi::class, ExperimentalFoundationApi::class)
@Composable
fun LazyListPage() {
    Column(
        modifier = Modifier
            .padding(horizontal = pagePadding)
            .verticalScroll(rememberScrollState())
    ) {
        PrimaryTitle("简介")
        BodyText("延迟列表，类似ListView RecyclerView，具备item回收复用，优化加载速度和内存占用，通常用于大量数据的列表展示")

        LargeSpacer()
        UlItem("LazyColumn")
        LabelText("竖向列表")
        Box(
            Modifier
                .fillMaxWidth()
                .height(300.dp)
                .border(1.dp, Color.Gray, RoundedCornerShape(10.dp)),
            contentAlignment = Alignment.BottomEnd
        ) {
            val lazyListState: LazyListState = rememberLazyListState()
            val scope = rememberCoroutineScope()
            val isFirstItemShowing = remember { mutableStateOf(true) }
            LaunchedEffect(lazyListState) {
                //启用一个附带效应，在协程作用域中，创建一个快照流，并处理第一个可见item的变化
                //快照流的特点时它会比较数据变化，若无变化则不会发送新的值，实现数据防抖
                // 这里监听列表是否滚动到第一个item
                snapshotFlow { lazyListState.firstVisibleItemIndex == 0 }.collect {
                    isFirstItemShowing.value = it
                }
            }
            LazyColumn(
                Modifier.fillMaxSize(),
                state = lazyListState,
                contentPadding = PaddingValues(10.dp),
                reverseLayout = false,
                verticalArrangement = Arrangement.SpaceBetween
            ) {
                (0..10000).forEach {
                    if (it % 100 == 0) {
                        stickyHeader {
                            Text(
                                "stickyHeader:${it / 100 * 100}~${it / 100 * 100 + 99}",
                                Modifier
                                    .fillMaxWidth()
                                    .background(MaterialTheme.colorScheme.background)
                            )
                        }
                    }
                    item {
                        Text("$it")
                    }
                }
            }
            if (!isFirstItemShowing.value) {
                FloatingActionButton({
                    scope.launch {
                        lazyListState.scrollToItem(0, 0)
                    }
                }) {
                    Icon(
                        Icons.Filled.ArrowBack,
                        "To top",
                        Modifier.rotate(90f),
                        MaterialTheme.colorScheme.onPrimary
                    )
                }
            }
        }
        MiniSpacer()
        OlItem(1, "state")
        LabelText("LazyList状态，提供了滚动状态获取与设置")
        MiniSpacer()
        OlItem(2, "contentPadding")
        LabelText("内容的padding，可以视为它在第一条数据的顶部、最后一条数据的底部、列表的左右添加padding，以往在RecyclerView中实现这种效果需要借助装饰器，这里倒是方便了")
        MiniSpacer()
        OlItem(3, "reverseLayout")
        LabelText("反转列表，从底部开始显示")
        MiniSpacer()
        OlItem(4, "verticalArrangement")
        LabelText("垂直方向的排布，效果与Column相同，在内容高度小于列表高度时起效果")
        MiniSpacer()
        OlItem(5, "horizontalAlignment")
        LabelText("横向对齐，效果与Column相同")
        MiniSpacer()
        OlItem(6, "item")
        LabelText("通过该方法向列表插入一个条目")
        MiniSpacer()
        OlItem(7, "items")
        LabelText("通过该方法向列表批量插入条目，可以通过contentType提高复用效率")
        MiniSpacer()
        OlItem(8, "stickyHeader")
        LabelText("头部粘性条目，可以很方便的实现列表item滚动到顶部时的吸附效果")

        LargeSpacer()
        UlItem("LazyRow")
        LabelText("横向列表")
        Box(
            Modifier
                .fillMaxWidth()
                .height(100.dp)
                .border(1.dp, Color.Gray, RoundedCornerShape(10.dp)),
            contentAlignment = Alignment.BottomEnd
        ) {
            val lazyListState: LazyListState = rememberLazyListState()
            val scope = rememberCoroutineScope()
            val isFirstItemShowing = remember { mutableStateOf(true) }
            LaunchedEffect(lazyListState) {
                //启用一个附带效应，在协程作用域中，创建一个快照流，并处理第一个可见item的变化
                //快照流的特点时它会比较数据变化，若无变化则不会发送新的值，实现数据防抖
                // 这里监听列表是否滚动到第一个item
                snapshotFlow { lazyListState.firstVisibleItemIndex == 0 }.collect {
                    isFirstItemShowing.value = it
                }
            }
            LazyRow(
                Modifier.fillMaxSize(),
                state = lazyListState,
                contentPadding = PaddingValues(10.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                (0..10000).forEach {
                    if (it % 100 == 0) {
                        stickyHeader {
                            Box(
                                Modifier
                                    .fillMaxSize()
                                    .background(MaterialTheme.colorScheme.background),
                                contentAlignment = Alignment.Center
                            ) {
                                Text("stickyHeader:${it / 100 * 100}~${it / 100 * 100 + 99}")
                            }
                        }
                    }
                    item {
                        Text(
                            "$it", Modifier
                                .padding(10.dp)
                                .background(
                                    MaterialTheme.colorScheme.primary, RoundedCornerShape(5.dp)
                                )
                                .padding(10.dp), MaterialTheme.colorScheme.onPrimary
                        )
                    }
                }
            }
            if (!isFirstItemShowing.value) {
                FloatingActionButton({
                    scope.launch {
                        lazyListState.scrollToItem(0, 0)
                    }
                }) {
                    Icon(
                        Icons.Filled.ArrowBack,
                        "To Start",
                        tint = MaterialTheme.colorScheme.onPrimary
                    )
                }
            }
        }
    }
}